package com.diandiansong.app.utils;

import com.diandiansong.app.App;
import com.diandiansong.app.entity.LoginInfo;
import com.diandiansong.app.entity.UploadInfo;
import com.diandiansong.app.event.FINISH;
import com.diandiansong.manager.entity.SalesLoginInfo;

import org.greenrobot.eventbus.EventBus;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import diandiansong.library.http.okhttputils.OkHttpUtils;
import diandiansong.library.http.okhttputils.builder.GetBuilder;
import diandiansong.library.http.okhttputils.builder.PostFormBuilder;
import diandiansong.library.http.okhttputils.callback.StringCallback;
import diandiansong.library.http.okhttputils.https.HttpsUtils;
import diandiansong.library.utils.BaseEntity;
import diandiansong.library.utils.CCallBack;
import diandiansong.library.utils.JsonParse;
import diandiansong.library.utils.Logger;
import diandiansong.library.utils.OnLoadingListener;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * API接口
 * http协议封装
 */
public class Api {

    // TODO: 2018/8/7 闪退token重载
    public static String TOKEN = null;

    public static String URL = "http://yidiann.com";

    public static String APP_UPDATE_URL_USER = "/update/version_user.xml";

    public static String APP_UPDATE_URL_MERCHANTS = "/update/version_merchants.xml";

    protected static Logger logger = Logger.getLogger();
    public static int PAGE_SIZE = 10;

    protected static final String PUCLIC_KEY =
            "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDgf1bNwZHVHJNT6uUQze13kfkFMrqzJ9Sb3FJRQl4FyX05FFpNGSPp44Q4eZxeU+7DeMYF/OHirzFeM4LYdCF" +
                    "/sNIWB55ocIDTuJsNCDlr40Fpt9T3HIDqG0aOOKRp0zBHpBS0IF63O3lz+PpcUdLp5hELYzJwo6EwdwEXTOp7wIDAQAB";


    ///////////////////////////////////////////////////////////////////////////
    // BASE METHON
    ///////////////////////////////////////////////////////////////////////////

    protected static <T> void post(String restapi, Map<String, String> params, OnLoadingListener oer, final CCallBack<T> callBack) {
        logger.d("post() called with: " + "restapi = [" + URL + restapi + "], params = [" + params + "], callBack = [" + callBack + "]");

        initSSH();
        preHandleParams(params);

        PostFormBuilder builder = OkHttpUtils.post().url(URL + restapi).params(params);
        if (TOKEN == null || TOKEN.isEmpty()) {
            if (App.isUserClient()) {
                TOKEN = LoginInfo.getToken(App.getApplication());

            } else {
                TOKEN = SalesLoginInfo.getToken(App.getApplication());
            }
        }
        if (TOKEN != null && !TOKEN.isEmpty()) {
            builder.addHeader("Authorization", "Bearer " + TOKEN + "");
        }
        if (restapi.contains("/api/auth/login")
                || restapi.contains("/api/sales/login")
                ) {//只有登录用v2
            builder.addHeader("Accept", "application/vnd.trading.v2+json");
        }
        builder.build().execute(getCallBack(restapi, oer, callBack));
    }

    private static void preHandleParams(Map<String, String> params) {
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String value = entry.getValue();
            if (value == null) {
                String key = entry.getKey();
                params.put(key, "");
            }
        }
    }

    public static <T> void get(String restapi, Map<String, String> params, OnLoadingListener oer, final CCallBack<T> callBack) {
        logger.d("post() called with: " + "restapi = [" + URL + restapi + "], params = [" + params + "], callBack = [" + callBack + "]");

        initSSH();
        preHandleParams(params);

        GetBuilder builder = OkHttpUtils.get().url(URL + restapi).params(params);
        if (TOKEN == null || TOKEN.isEmpty()) {
            if (App.isUserClient()) {
                TOKEN = LoginInfo.getToken(App.getApplication());

            } else {
                TOKEN = SalesLoginInfo.getToken(App.getApplication());
            }
        }
        if (TOKEN != null && !TOKEN.isEmpty()) {
            builder.addHeader("Authorization", "Bearer " + TOKEN + "");
        }
        builder.build().execute(getCallBack(restapi, oer, callBack));
    }

    private static void initSSH() {
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(null, null, null);
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .hostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                })
                .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                .retryOnConnectionFailure(true)
                .connectTimeout(30, TimeUnit.SECONDS)
                .build();
        OkHttpUtils.initClient(okHttpClient);
    }

    private static <T> StringCallback getCallBack(final String restapi, final OnLoadingListener oer, final CCallBack<T> callBack) {
        return new StringCallback() {

            long mShowStart;

            @Override
            public String parseNetworkResponse(Response response, int id) throws IOException {
//                long now = new Date().getTime();
//                long c = now - mShowStart;
//                if (c < 600) {
//                    try {
//                        Thread.sleep(600 - c);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                }
                return super.parseNetworkResponse(response, id);
            }

            @Override
            public void onBefore(Request request, int id) {
                super.onBefore(request, id);
                if (oer != null) {
                    oer.onLoading();
                }
                mShowStart = new Date().getTime();
            }

            @Override
            public void onAfter(int id) {
                super.onAfter(id);
                if (oer != null) {
                    oer.onLoaded();
                }
            }

            @Override
            public void onError(String response, Call call, Exception e, int id) {
                logger.e("onError() called with: " + "response = [" + response + "], call = [" + call + "], e = [" + e + "], id = [" + id + "]");
                if (response != null) {
                    onResponse(response, id);

                } else {
                    if (callBack != null)
                        callBack.onFailure(-999, "网络异常");
                }
            }

            @Override
            public void onResponse(String response, int id) {
                logger.d(" " + restapi + " [" + response + "]");
                if (callBack == null) {
                    return;
                }
                if (restapi.equals("/update/version_user.xml")||restapi.equals("/update/version_merchants.xml")) {
                    try {
                        callBack.onSuccess((T) response);
                    } catch (Exception e) {
                        callBack.onFailure(-999, "解析出错");
                    }
                    return;
                }
                //先转化为基础实体，判空及errorCode
                //maybe data is other typet
                BaseEntity baseEntity = JsonParse.parse(response, BaseEntity.class);
                //提取错误信息直接回调
                if (baseEntity != null) {
                    if (!baseEntity.isSuccess()) {
                        String msg = baseEntity.getMessage();
                        if (baseEntity.getStatusCodeInt() == 401) {
                            msg = "账号信息失效,请重新登录";
                            LoginInfo.clearToken(App.getApplication());
                            EventBus.getDefault().post(new FINISH());
                        }
                        callBack.onFailure(baseEntity.getStatusCodeInt(), msg);

                    } else {
                        Type type = ((ParameterizedType) callBack.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
                        T entity = JsonParse.parseObjFromType(response, type);
                        if (entity != null) {
                            try {
                                callBack.onSuccess(entity);
                            } catch (Exception e) {
                                logger.e(e.toString());
                                callBack.onFailure(-999, "程序异常");
                            }

                        } else {
                            logger.e("tag:" + id + ", onError() called with: " + "parse = [error]");
                            callBack.onFailure(-999, "解析失败");
                        }
                    }

                } else {
                    logger.e("tag:" + id + ", onError() called with: " + "parse = [error]");
                    callBack.onFailure(-999, "解析失败");
                }
            }
        };
    }

    public static void upload(File file, final CCallBack<UploadInfo> callBack) {
        OkHttpUtils.post().url(URL + "/api/upload/image")
                .addFile("photo", file.getName(), file).build().execute(getCallBack("upload", null, callBack));
    }

    public static void uploadM(File file, final CCallBack<UploadInfo> callBack) {
        OkHttpUtils.post().url(URL + "/api/sales/upload/image")
                .addFile("photo", file.getName(), file).build().execute(getCallBack("upload", null, callBack));
    }
}